﻿/*
 * Routing Table
 * 
 * Author: snowdreamist
 * Date: 2011/11/22
 * 
 */

using System;
using System.Collections.Generic;
using System.Net;
using System.Linq;
using System.Text;
using BitTorrentSharp.Maths;

namespace BitTorrentSharp.DHT
{
    public sealed class RoutingTable
    {
        #region static

        /// <summary>
        /// 0
        /// </summary>
        public static readonly BigInteger Low = new BigInteger(new UInt64[] { 0 });
        /// <summary>
        /// 2 ^ 160 - 1
        /// </summary>
        public static readonly BigInteger High = new BigInteger(new byte[] { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff });

        #endregion
        /// <summary>
        /// Constructor, internal
        /// </summary>
        internal RoutingTable(
            DHTEngine engine,
            Node currentNode
            )
        {
            if (engine == null)
                throw new ArgumentNullException("engine");
            if (currentNode == null)
                throw new ArgumentNullException("rootNode");

            this.Engine = engine;
            this.CurrentNode = currentNode;
            this.RootBucket = new Bucket(this.Engine, Low, High, null);
        }

        public DHTEngine Engine { get; private set; }
        /// <summary>
        /// Current node
        /// </summary>
        public Node CurrentNode { get; private set; }
        /// <summary>
        /// Root bucket
        /// </summary>
        public Bucket RootBucket { get; private set; }

        #region basic operations
        /// <summary>
        /// Add a DHT node to routing table
        /// </summary>
        /// <param name="id">node id</param>
        /// <param name="endPoint">node endpoint</param>
        /// <returns>Add succeed or not</returns>
        public bool AddNode(NodeID id, IPEndPoint endPoint)
        {
            Node replacedNode;
            return this.RootBucket.AddNode(this.Engine.NodeFactory.CreateNode(id, endPoint), out replacedNode);
        }
        /// <summary>
        /// Refresh routing table
        /// </summary>
        public void Refresh()
        {
            this.RootBucket.Refresh();
        }

        #endregion
    }
}
